<!-- 视频播放组件 -->

<template>
	<view>
		<!-- 相对定位占位容器 -->
		<focus-box 
			bg="black"
			width="750" 
			height="422" 
			position="relative" 
		>
			
			<focus-box 
				top="0"
				left="0" 
				mode="col" 
				width="750" 
				height="422" 
				align="center"
				justify="center" 
				position="absolute" 
			>
				<image 
					style="width:750rpx; height:422rpx;" 
					src="@/pagesB/static/img/video/placeholder.jpg"
				/>
			</focus-box>
			
			<!-- video组件容器 -->
			<focus-box 
				top="0"
				left="0" 
				width="750" 
				height="422" 
				position="absolute" 
				v-show="state.isShow"
			>
				
				<!-- v-show='!demaxiya && state.isShow' -->
				<!-- 视频播放组件 -->
				<video 
					id="djyMediaVideo" 
					play-btn-position="bottom"
					class="video-official-style"
					:src="srcStatus"
					:controls="true" 
					:autoplay="true"
					:show-progress="true" 
					:vslide-gesture="true"
					:enable-play-gesture="true" 
					:show-center-play-btn="false" 
					@play="onPlay" 
					@pause="onPause" 
					@ended="onEnded"
					@timeupdate="onTimeupdate"
					@loadedmetadata="onLoadedmetadata"
					@controlstoggle="onControlstoggle"
					@fullscreenchange="onFullscreenchange"
				>
					<!-- 中间播放按钮 -->
					<view 
						v-if="state.isPlaying!=true" 
						class="video-box-play-center"
						@click.stop="centerPlayClick"
					>
						<image 
							class="video-img-play-center" 
							src="@/pagesB/static/img/video/play_border.png"
						/>
					</view>
					<!-- 插槽 -->
					<slot></slot>
				</video>
			</focus-box>
		</focus-box>
	</view>
</template>


<script>
	/**
	 * 视频播放组件
	 * @description 视频播放组件，杜先生开发
	 * @property {String} tag 组件标识，默认：video-public
	 * @property {String} src 视频资源地址
	 * @property {String,Number} jump 初始要跳转到的秒数，单位：s
	 * @property {String,Number} numcall 每10%进度的回调，设定值单位：%，默认：10
	 * @property {String,Boolean} openplay = [true|false] 是否开启播放功能，默认：true
	 *   @value true 开启播放功能，默认项
	 *   @value false 关闭播放功能
	 * @property {String,Boolean} openlegal = [true|false] 是否检测观看合法性，默认：true
	 *   @value true 不允许拖动进度条快进，默认项
	 *   @value false 可以随意拖动进度条
	 * @event {Function()} play 触发播放
	 * @event {Function()} pause 触发暂停
	 * @event {Function()} ended 播放完毕
	 * @event {Function()} timeupdate 播放进度更新
	 * @event {Function()} segmentupdate 分段更新到达，如：10%/20%/30%
	 */
	export default {
		name: 'video-public',
		
		props: {
			"tag": { type: String, default: 'video-public' },
			"src": { type: String, default: '' },
			"duration":{ type: String, default: ''},
			"jump": { type: [String,Number], default: 0 },
			"numcall": { type: [String,Number], default: 10 },
			"openplay": { type: [String,Boolean], default: true },
			"openlegal": { type: [String,Boolean], default: true },
		},
		
		// 页面数据
		data() {
			return {
				// 计时器对象
				timer: {
					build: null, // 获取video (定时器)
					jump: null, // 初始自动跳转 (定时器)
				},
				// 配置类信息
				config: {
					videoContext: null, // 视频播放器对象
				},
				// 状态信息
				state: {
					isShow: false, // 是否显示video组件
					isPlaying: false, // 是否正处于"播放中"状态
					isFullscreen: false, // 是否正处于"全屏"状态
				},
				
				// 状态限制信息
				limit: {
					isJumpNeed: true, // 是否需要初始跳转
					isCanTimeupdate: true, // 是否允许timeupdate触发
				},
				
				// 播放实时数据信息
				playInfo: {
					all: 0, // 总的秒数 (s，真实播放有6位小数，向小取整)
					seconds: 0, // 当前已经播放秒数 (s，真实播放有6位小数，四舍五入)
					max: 0, // 可以播放的最大秒数 (s，整数)
					progress: 0, // 当前进度：0~100 (%，整数)
					quDuan: 0, // 最近一次触发的进度区段 (如果是100%的视频，每10%回调，总量那么相当于有10段)
				},
				srcStatus:'https://vod.cqjjb.cn/f04312c0cfca71eebfc44531948c0102/f443c674f0cf4a1aa716dd43944c57d8-7305093641c874ca152cedc694b9dbfa-ld.mp4',
			}
		},
		
		// 实例挂载完毕
		mounted() {
			// 获取video实例对象
			this.config.videoContext = uni.createVideoContext('djyMediaVideo', this);
			
		},
		
		// 数据监听
		watch: {
			// 媒体资源网络地址 改变了
			src: {
				handler(newValue, oldValue) {
					console.log('视频链接发生变化',newValue)
					// 如果地址有效，那么显示播放器组件
					if (typeof(newValue) == "string" && newValue.length>6) { 
						this.state.isShow = true;
						this.srcStatus = 'https://vod.cqjjb.cn/f04312c0cfca71eebfc44531948c0102/f443c674f0cf4a1aa716dd43944c57d8-7305093641c874ca152cedc694b9dbfa-ld.mp4'
						if(newValue.split(' || ').length > 1){
							console.log(this.config.videoContext, this.jump)
							this.pause()
							this.onEnded()
						}
					} else {
						this.state.isShow = false;
					}
					// 初始化组件数据
					this.initData();
					setTimeout(() => this.config.videoContext.play(),600)
				},
				immediate: true // 首次就执行
			},
		},
		
		// 组件销毁之前
		beforeDestroy() {
			// 关闭屏幕常亮
			uni.setKeepScreenOn({ keepScreenOn: false });
			// 暂停播放
			this.pause();
			// 注销定时器
			for (let key in this.timer) { 
				if (this.timer[key]) {
					clearTimeout(this.timer[key]);
				} 
			}
		},
		
		// 页面事件
		methods: {
			
			// ======================================== 父级调用
			// 开始播放
			play() { 
				if (this.config.videoContext) {
					this.config.videoContext.play(); 
				} 
			},
			// 暂停播放
			pause() { 
				if (this.config.videoContext) { 
					this.config.videoContext.pause(); 
				} 
			},
			// 进入全屏
			requestFullScreen() { 
				if (this.config.videoContext) { 
				this.config.videoContext.requestFullScreen(); 
				} 
			},
			// 退出全屏
			exitFullScreen() { 
				if (this.config.videoContext) {
					this.config.videoContext.exitFullScreen(); 
				} 
			},
			// ======================================== 数据处理
			// 返回数据通用结构，参数： nameC-@的方法名称
			callfunction(nameC) {
				// 组装要生成的定时器名称
				var name_timer = 'call_' + nameC;
				// 是否已经存在该定时器对象
				if (!this.timer[name_timer]){
					// 如果没有方法名称参数
					if (!nameC) { nameC = 'callback'; }
					// 返回值
					var back = {
						tag: this.tag, // 组件的标识
						detail: {
							duration: this.playInfo.all, // 资源总时长：s
							currentTime: this.playInfo.seconds, // 当前播放到的时间秒数：s
							progress: this.playInfo.progress, // 已经播放的进度：%
						}
					};
					// 定时器对象
					this.timer[name_timer] = setTimeout(()=>{
						// 初始化定时器对象
						if (this.timer[name_timer]) { clearTimeout(this.timer[name_timer]); }
						this.timer[name_timer] = null;
						// 组件监听事件触发
						this.$emit(nameC, back);
					}, 100);
				}
			},
			// 组件数据初始化
			initData() {
				// 初始化组件数据
				if (this.config.videoContext){
					// 进度条回0
					this.config.videoContext.pause(); // 先暂停播放
					this.config.videoContext.seek(0); // 回到0s
				}
				// 数据还原
				this.playInfo.all = 0;
				this.playInfo.seconds = 0;
				this.playInfo.max = 0;
				this.playInfo.progress = 0;
				this.playInfo.quDuan = 0;
				// 状态数据
				this.limit.isJumpNeed = true;
				this.limit.isCanTimeupdate = true;
			},
			// ======================================== 元素事件
			// ----------------------- video组件回调
			// 视频元数据加载完成时触发
			onLoadedmetadata(ev) {
				// 只有未获取或视频信息才执行
				if (this.playInfo.all <= 0){
					// 总时长 赋值(向小取整)
					this.playInfo.all = Math.floor(Number(ev.detail.duration)); 
					// 如果开启了合法性验证
					if (this.openlegal == true) { this.playInfo.max = this.jump>this.playInfo.all ? this.playInfo.all : this.jump; }
					// 不做限制，那么让 最大播放秒 = 视频长度秒
					else { this.playInfo.max = this.playInfo.all; }
				}
			},
			// 进度条显示隐藏
			onControlstoggle(e){
				// 事件回调
				this.$emit('controlstoggle', e.detail.show);
			},
			// 触发 播放
			onPlay() {
				// 开启屏幕常亮
				uni.setKeepScreenOn({ keepScreenOn: true });
				// 改变播放状态
				this.state.isPlaying = true;
				// 1. 没有开启播放功能，就暂停
				if(this.srcStatus !== 'https://vod.cqjjb.cn/f04312c0cfca71eebfc44531948c0102/f443c674f0cf4a1aa716dd43944c57d8-7305093641c874ca152cedc694b9dbfa-ld.mp4'){
				  if (this.openplay == false){
					// 退出全屏
					this.exitFullScreen();
					// 暂停播放
					this.pause();
				  }
				  // 2. 如果需要初始跳转
				  else if (this.limit.isJumpNeed==true && this.jump > 0 && this.jump < this.playInfo.all){
					// 延时进行跳转
					if (this.timer.jump) { clearTimeout(this.timer.jump); }
					this.timer.jump = setTimeout(() => {
					  // 跳转进度到jump参数秒数
					  this.config.videoContext.seek(parseInt(this.jump));
					  // 修改状态为false
					  this.limit.isJumpNeed = false;
					}, 1000);
				  }
				  // 事件回调
				  this.callfunction('play');
				}
		
			},
			// 触发 暂停
			onPause() {
				// 改变播放状态
				this.state.isPlaying = false;
				// 事件回调
				this.callfunction('pause');
			},
			// 触发 播放结束
			onEnded() {
				// 合法播放执行
				if(this.srcStatus === 'https://vod.cqjjb.cn/f04312c0cfca71eebfc44531948c0102/f443c674f0cf4a1aa716dd43944c57d8-7305093641c874ca152cedc694b9dbfa-ld.mp4'){
					this.srcStatus = this.src.split(' || ').length > 1 ? this.src.split(' || ')[0] : this.src
					this.initData()
					this.callfunction('initEnd');
					setTimeout(()=>{
						if (this.limit.isJumpNeed==true && this.jump > 0 && this.jump < this.playInfo.all){
							// 跳转进度到jump参数秒数
							this.config.videoContext.seek(parseInt(this.jump));
							// 修改状态为false
							this.limit.isJumpNeed = false;
						}else{
							this.config.videoContext.play()
						}
					},1000)
				}else{
					if (this.playInfo.progress >= 100){
						// 改变播放状态为 false
						this.isPlaying = false;
						// 将数值状态全部设置为100%状态
						this.playInfo.seconds = this.playInfo.all;
						this.playInfo.max = this.playInfo.all;
						this.playInfo.progress = 100;
						// 事件回调
						this.callfunction('ended');
					}
				}
				
			},
			// 触发 进入和退出全屏
			onFullscreenchange(ev) {
				// 状态改变
				this.state.isFullscreen = ev.detail.fullScreen;
			},
			// 触发 播放进度变化
			onTimeupdate(ev) {
				if(this.srcStatus!=='https://vod.cqjjb.cn/f04312c0cfca71eebfc44531948c0102/f443c674f0cf4a1aa716dd43944c57d8-7305093641c874ca152cedc694b9dbfa-ld.mp4'){
					// 是否允许执行方法，防止计算量过大，导致卡顿
					if (this.limit.isCanTimeupdate){
						// 状态标记为“不允许执行”
						this.limit.isCanTimeupdate = false;
						// -------------------------------------- 当前观看时长
						// video返回的当前位置s
						var time_now = ev.detail.currentTime ? ev.detail.currentTime : 0;
						// 播放位置 赋值(四舍五入)
						this.playInfo.seconds = Math.round(Number(time_now));
						
						// -------------------------------------- 观看合法性判定
						// 如果用了非法手段
						if (this.playInfo.seconds > (this.playInfo.max + 2)) {
							// 回到合法播放的位置
							this.config.videoContext.seek(this.playInfo.max);
						}else {// 合法播放执行
							
							// 覆盖赋值最大播放秒数
							if (this.playInfo.seconds > this.playInfo.max) {
								// 最大合法播放秒数 赋值
								this.playInfo.max = this.playInfo.seconds;
							}
							
							// -------------------------------------- 播放进度计算
							// 1. 当前播放时间为0
							if (this.playInfo.seconds <= 0) {
								// 播放进度 = 0
								this.playInfo.progress = 0;
							}
							// 2. 播放时间大于等于视频时长
							else if (this.playInfo.seconds >= this.playInfo.all) {
								// 播放进度 = 100
								this.playInfo.progress = 100;
							}
							// 3. 其它正常情况
							else {
								// 播放进度 初步计算 (向小取整)
								this.playInfo.progress = Math.floor(this.playInfo.seconds / this.playInfo.all * 100);
							}
							// 进度更新 传递父级
							if (this.playInfo.progress > 0 && this.playInfo.progress < 100)
							{
								// 播放进度更新事件 回父
								this.callfunction('timeupdate');
								
								// -------------------------------------- 到达区段计算
								// 如果是100%的视频，每10%回调，那么相当于有10段
								var duan_now = parseInt(this.playInfo.progress / this.numcall); // 当前到达段，如：4
								// 如果当前段 > 上一次记录的段
								if (duan_now > this.playInfo.quDuan){
									// 记录的段 重新赋值
									this.playInfo.quDuan = duan_now;
									// 分段更新到达
									this.callfunction('segmentupdate');
								}
							}	
						}
						// 状态标记为“允许执行”
						this.limit.isCanTimeupdate = true;
					}
				}
				
			},
			// ----------------------- 屏幕中心控制
			// 中心播放按钮 点击
			centerPlayClick() { this.play(); },
		},
		
	}
</script>


<style scoped>
	/* video组件样式 */
	.video-official-style{ 
		width: 750rpx; 
		height: 422rpx; 
		position: relative; 
		background-color: #000000; 
	}
	/* 中间播放按钮容器 */
	.video-box-play-center{ 
		position: absolute; 
		left: 0; 
		top: 0; 
		right: 0;
		bottom: 0; 
		display: flex; 
		flex-direction: column; 
		justify-content: center; 
		align-items: center; 
	}
	/* 中间播放按钮图片 */
	.video-img-play-center{ 
		width: 64rpx; 
		height: 64rpx; 
	}
</style>